const satellite = require('satellite.js')
const moment = require('moment')
const julian = require('julian')

/*
根据卫星显示的起始时间，终止时间，tle轨道两行数得出czml文件，时间为js的Date对象，tles为对象数组，对象格式为
{
name：xx，
tle1：xx，
tle2：xx
}
*/
export default function tles2czml(startTime, endTime, tles) {
  // 计算起始时间和终止时间相隔的分钟数
  let minsInDuration = (endTime.getTime() - startTime.getTime()) / 6000; //mins
  //设置为开始时间
  let initialTime = moment(startTime.toISOString()).toISOString();
  //设置为结束时间
  endTime = moment(endTime.toISOString()).toISOString();
  // 初始化czml数据，创建场景信息
  let tempCZML = [];
  tempCZML.push({
    "id": "document",
    "name": "CZML Point - Time Dynamic",
    "version": "1.0",
    "clock": {
      "interval": `${initialTime}/${endTime}`,
      "multiplier": 1,
      "range": "LOOP_STOP",
      "step": "SYSTEM_CLOCK"
    }
  }, )

  // 处理每一个sat
  for (let no = 0; no < tles.length; no++) {
    if (!tles[no].name) {
      console.log("请输入第" + no + 1 + "个卫星的名称");
      return
    };
    if (!tles[no].tle1) {
      console.log("请输入第" + no + 1 + "个卫星的第一个两行数");
      return
    };
    if (!tles[no].tle2) {
      console.log("请输入第" + no + 1 + "个卫星的第二个两行数");
      return
    };
    let sat_name = tles[no].name;
    // 保存位置信息
    let res = [];
    let satrec
    satrec = satellite.twoline2satrec(tles[no].tle1, tles[no].tle2);
    //satrec.no：以弧度/分钟为单位的平均运动，一天有1440分钟，一弧度是0.159155圈
    // to go from RAD/DAY -> REV/DAY: rad * 1440 * 0.159155
    //to go from REV/PER DAY to MINS/REV -> 1440/RevPerDay
    let totalIntervalsInDay = satrec.no * 1440 * 0.159155; //1440 = min && 0.159155 = 1turn
    // 获得运行一圈的分钟数
    let minsPerInterval = 1440 / totalIntervalsInDay; // mins for 1 revolution around earth
    // intervalTime 取起始时间 格式为2008-09-20T12:25:40.104Z
    let intervalTime = moment(startTime.toISOString()).toISOString()

    let leadIntervalArray = [];
    let trailIntervalArray = [];
    console.log("Setting intervals...", minsPerInterval);
    // 注意：这里之所以要倒过来求leadInterval和trailInterval是因为如果正着求，很有可能在终止时刻卫星并没有运行完一圈，导致轨道只显示一半
    for (let i = minsInDuration; i >= 0; i -= minsPerInterval) {
      if (i <= minsPerInterval) { // intial interval 
        let currentOrbitalInterval = {
          "interval": `${startTime}/${intervalTime}`,
          "epoch": `${startTime}`,
          "number": [
            0, minsPerInterval * 60,
            minsPerInterval * 60, 0
          ]
        }
        let currTrail = {
          "interval": `${startTime}/${intervalTime}`,
          "epoch": `${startTime}`,
          "number": [
            0, 0,
            minsPerInterval * 60, minsPerInterval * 60
          ]
        }
        leadIntervalArray.push(currentOrbitalInterval);
        trailIntervalArray.push(currTrail);
      } else { //not initial so make intervals 
        let previousIntervalTime = moment(intervalTime).add(-minsPerInterval, 'm').toISOString();
        let currentOrbitalInterval = {
          "interval": `${previousIntervalTime}/${intervalTime}`,
          "epoch": `${previousIntervalTime}`,
          "number": [
            0, minsPerInterval * 60,
            minsPerInterval * 60, 0
          ]
        }
        let currTrail = {
          "interval": `${previousIntervalTime}/${intervalTime}`,
          "epoch": `${previousIntervalTime}`,
          "number": [
            0, 0,
            minsPerInterval * 60, minsPerInterval * 60
          ]
        }
        intervalTime = moment(intervalTime).add(-minsPerInterval, 'm').toISOString();
        leadIntervalArray.push(currentOrbitalInterval);
        trailIntervalArray.push(currTrail);
      }
    }
    // Seconds between current time and epoch time
    let sec = (startTime - julian.toDate(satrec.jdsatepoch)) / 1000;
    console.log(startTime, julian.toDate(satrec.jdsatepoch), sec);
    for (let i = sec; i <= sec + minsInDuration * 60; i++) { //每60秒计算一个位置信息，最后采用拉格朗日插值法处理数据
      // 根据当前时间距tle两行数历元时刻的分钟数，计算当前卫星位置和速度
      let positionAndVelocity = satellite.sgp4(satrec, i * 0.0166667); // 0.0166667min = 1sec
      // 地惯坐标系
      let positionEci = positionAndVelocity.position;
      positionEci.x = positionEci.x * 1000;
      positionEci.y = positionEci.y * 1000;
      positionEci.z = positionEci.z * 1000;
      // let velocityEci = positionAndVelocity.velocity;
      // velocityEci.x = velocityEci.x * 1000;
      // velocityEci.y = velocityEci.y * 1000;
      // velocityEci.z = velocityEci.z * 1000;

      res.push(i - sec, positionEci.x, positionEci.y, positionEci.z);
    }
    let initialCZMLProps = {
      "id": `${sat_name}`,
      "name": `${sat_name}`,
      "availability": `${initialTime}/${endTime}`,
      "label": {
        "fillColor": {
          "rgba": [
            255, 0, 255, 255
          ]
        },
        "font": "11pt Lucida Console",
        "horizontalOrigin": "LEFT",
        "outlineColor": {
          "rgba": [
            0, 0, 0, 255
          ]
        },
        "outlineWidth": 2,
        "pixelOffset": {
          "cartesian2": [
            12, 0
          ]
        },
        "show": true,
        "style": "FILL_AND_OUTLINE",
        "text": `${sat_name}`,
        "verticalOrigin": "CENTER"
      },
      "path": {
        "show": [{
          "interval": `${initialTime}/${endTime}`,
          "boolean": true
        }],
        "width": 3,
        "material": {
          "solidColor": {
            "color": {
              "rgba": [
                // 随机生成轨道颜色
                Math.floor(255 * Math.random(0, 1)), Math.floor(255 * Math.random(0, 1)), Math.floor(255 * Math.random(0, 1)), 255
              ]
            }
          }
        },
        "resolution": 120,
        // The time ahead of the animation time, in seconds, to show the path.
        "leadTime": leadIntervalArray,
        // The time behind the animation time, in seconds, to show the
        "trailTime": trailIntervalArray
      },
      "model": {
        "show": true,
        "gltf": "../../../../../public/static/satelliteModel/scene.gltf",
        "minimumPixelSize": 50,
      },
      "position": {
        // 采用拉格朗日插值法
        "interpolationAlgorithm": "LAGRANGE",
        // 1为线性插值，2为平方插值
        "interpolationDegree": 2,
        // 参考坐标系，地惯坐标系
        "referenceFrame": "INERTIAL",
        "epoch": `${initialTime}`,
        "cartesian": res
      }
    }
    tempCZML.push(initialCZMLProps);
  }
  return tempCZML;
}
